
#include "Api_Welding.h"
#include <sstream>
#include <iomanip>
#include <opencv2/opencv.hpp>
#include <string>
#include <filesystem>
#include <algorithm>
namespace fs = std::filesystem;
long long count = 1;

WeldingDetector::WeldingDetector() 
{
    m_Detector = std::vector<OVYOLOV8>(WORKNUM);
    m_SegDectector = std::vector<OVYOLOV8Seg>(WORKNUM);
    m_Consumers = std::vector<std::thread>(WORKNUM);
    conf_thresh = 0.5;
    nms_thresh = 0.3;
    Segconf_thresh = 0.5;
    Segnms_thresh = 0.3;
    m_initalized = false;
}

bool WeldingDetector::Initialize(Params params)
{
    std::string weldingdetectorfile = params.weldingdetectorfile;
    conf_thresh = params.conf_thresh;
    nms_thresh = params.nms_thresh;
    std::string Segweldingdetectorfile = params.Seg_weldingdetectorfile;
    Segconf_thresh = params.Seg_conf_thresh;
    Segnms_thresh = params.Seg_nms_thresh;

    weldingdetectorfile = GetProgramDir() + "/weights/" + weldingdetectorfile;
    Segweldingdetectorfile = GetProgramDir() + "/weights/" + Segweldingdetectorfile;
    for (int i = 0; i < WORKNUM; i++) 
    {
        m_SegDectector[i].LoadOVModel(Segweldingdetectorfile.c_str(), -1, false);
        m_Detector[i].LoadOVModel(weldingdetectorfile.c_str(), -1, false);
        cv::Mat image = cv::Mat::zeros(cv::Size(640, 640), CV_8UC3);//看是否需要替换正常图进行预热
        std::vector<BBox> bboxs;
        std::vector<Instance> Segbboxs;
        float confidence = 0.5;
        float nms = 0.3;
        for (int j = 0; j < 10; j++)
        {
            m_Detector[i].Infer(image, bboxs, confidence, nms);
            m_SegDectector[i].Infer1(image, Segbboxs, confidence, nms);
        }
    }

    m_initalized = true;
    return true;
}
float scale_grobal = 1, scale_grobalPlus = 1;
cv::Mat WeldingDetector::resize_with_padding(const cv::Mat& input, int target_width, int target_height,
    const cv::Scalar& padding_color) {
    // 获取原始尺寸
    int original_width = input.cols;
    int original_height = input.rows;

    // 计算缩放比例
    float scale = (std::min)(static_cast<float>(target_width) / original_width,
        static_cast<float>(target_height) / original_height);
    scale_grobal = scale;
    scale_grobalPlus = scale_grobal;

    // 计算新尺寸（保持宽高比）
    int new_width = static_cast<int>(original_width * scale);
    int new_height = static_cast<int>(original_height * scale);

    // 调整图像大小
    cv::Mat resized;
    cv::resize(input, resized, cv::Size(new_width, new_height), 0, 0, cv::INTER_LINEAR);

    // 创建目标图像并填充
    cv::Mat output(target_height, target_width, input.type());
    output.setTo(padding_color);

    // 计算放置位置（居中）
    int x_offset = (target_width - new_width) / 2;
    int y_offset = (target_height - new_height) / 2;

    // 确保 ROI 不超出边界
    x_offset = (((0) > (x_offset)) ? (0) : (x_offset));
    y_offset = (((0) > (y_offset)) ? (0) : (y_offset));
    new_width = (((new_width) < (target_width - x_offset)) ? (new_width) : (target_width - x_offset));
    new_height = (((new_height) < (target_height - y_offset)) ? (new_height) : (target_height - y_offset));

    // 将调整后的图像复制到中心
    if (new_width > 0 && new_height > 0) {
        cv::Mat roi(output, cv::Rect(x_offset, y_offset, new_width, new_height));

        // 确保类型匹配
        if (resized.type() != roi.type()) {
            cv::Mat converted;
            resized.convertTo(converted, roi.type());
            converted.copyTo(roi);
        }
        else {
            resized.copyTo(roi);
        }
    }

    return output;
}

cv::Mat WeldingDetector::resize_with_paddingPlus(const cv::Mat& input, int target_width, int target_height,
    const cv::Scalar& padding_color) {
    // 获取原始尺寸
    int original_width = input.cols;
    int original_height = input.rows;

    // 计算缩放比例
    float scale = (std::min)(static_cast<float>(target_width) / original_width,
        static_cast<float>(target_height) / original_height);
    scale_grobalPlus = scale * scale_grobalPlus;

    // 计算新尺寸（保持宽高比）
    int new_width = static_cast<int>(original_width * scale);
    int new_height = static_cast<int>(original_height * scale);

    // 调整图像大小
    cv::Mat resized;
    cv::resize(input, resized, cv::Size(new_width, new_height), 0, 0, cv::INTER_LINEAR);

    // 创建目标图像并填充
    cv::Mat output(target_height, target_width, input.type());
    output.setTo(padding_color);

    // 计算放置位置（居中）
    int x_offset = (target_width - new_width) / 2;
    int y_offset = (target_height - new_height) / 2;

    // 确保 ROI 不超出边界
    x_offset = (((0) > (x_offset)) ? (0) : (x_offset));
    y_offset = (((0) > (y_offset)) ? (0) : (y_offset));
    new_width = (((new_width) < (target_width - x_offset)) ? (new_width) : (target_width - x_offset));
    new_height = (((new_height) < (target_height - y_offset)) ? (new_height) : (target_height - y_offset));

    // 将调整后的图像复制到中心
    if (new_width > 0 && new_height > 0) {
        cv::Mat roi(output, cv::Rect(x_offset, y_offset, new_width, new_height));

        // 确保类型匹配
        if (resized.type() != roi.type()) {
            cv::Mat converted;
            resized.convertTo(converted, roi.type());
            converted.copyTo(roi);
        }
        else {
            resized.copyTo(roi);
        }
    }

    return output;
}

// 多光源图像拼接函数
cv::Mat WeldingDetector::MergeMultiLightImages(const std::vector<cv::Mat>& images, int fusionMethod = 0)
{
    if (images.empty()) return cv::Mat();

    // Step 1: 图像对齐（假设已粗略对齐，否则需特征匹配）
    std::vector<cv::Mat> alignedImages = images;

    // Step 2: 光照归一化（CLAHE增强对比度）
    std::vector<cv::Mat> normalizedImages;
    cv::Ptr<cv::CLAHE> clahe = cv::createCLAHE(2.0, cv::Size(32, 32));
    for (const auto& img : alignedImages) {
        cv::Mat normalized;
        if (img.channels() == 3) {
            std::vector<cv::Mat> channels;
            cv::split(img, channels);
            for (auto& ch : channels) clahe->apply(ch, ch);
            cv::merge(channels, normalized);
        }
        else {
            clahe->apply(img, normalized);
        }
        normalizedImages.push_back(normalized);
    }
    //std::vector<cv::Mat> normalizedImages = images;
    // Step 3: 图像融合（根据需求选择方法）
    cv::Mat result;
    if (fusionMethod == 0) {
        // 方法1: 简单平均（适用于均匀光照补偿）
        result = cv::Mat::zeros(normalizedImages[0].size(), normalizedImages[0].type());
        for (const auto& img : normalizedImages) {
            result += img / static_cast<int>(normalizedImages.size());
        }
    }
    else {
        // 方法2: 最大值合成（突出不同光源的特征）
        result = normalizedImages[0].clone();
        for (size_t i = 1; i < normalizedImages.size(); ++i) {
            //std::max(result, normalizedImages[i], result);
        }
    }
    return result;
}

void WeldingDetector::SetIuputImages(std::vector<cv::Mat>& image, int id)
{
    if (image.empty() || image.size() != 4)
        return;
    else
    {
        //拼接裁剪图像
        cv::Mat src;
        int firstWidth = image[0].cols;
        int firstHeight = image[0].rows;
        for (int i = 0; i < image.size(); i++)
        {
            if (image[i].cols != firstWidth || image[i].rows != firstHeight)
            {
                src = image[0];
                break;
            }
        }
        if (src.empty())
        {
            src = MergeMultiLightImages(image);
        }
        m_Images.push(std::pair<cv::Mat, int>(src, id));
    }
}
void WeldingDetector::SetIuputImagessignal(cv::Mat& image, int id)
{
    if (image.empty())
        return;
    else
    {
        //拼接裁剪图像
        cv::Mat src;
        //src = MergeMultiLightImages(image);
        src = image;
        m_Images.push(std::pair<cv::Mat, int>(src, id));
    }
}

void WeldingDetector::ProducerFunc() 
{
    while (true)
    {
        if (m_initalized) 
        {
            
            if (m_Images.size() > 0) 
            {
                std::lock_guard<std::mutex> lock(mtx);
                m_ImageTeams.push(m_Images.front());
                m_Images.pop();
                cvr.notify_one(); 
            }          
            
        }      
    }
}

void WeldingDetector::ConsumerFunc(int id)
{
    while (true)
    {
        if (m_initalized) 
        {
            std::unique_lock<std::mutex> lock(mtx);
            cvr.wait(lock, [] {return !Obj<WeldingDetector>::GetInstance()->m_ImageTeams.empty(); }); 

            if (Obj<WeldingDetector>::GetInstance()->m_ImageTeams.size() > 0)
            {
                cv::Mat src = Obj<WeldingDetector>::GetInstance()->m_ImageTeams.front().first;
                int index = Obj<WeldingDetector>::GetInstance()->m_ImageTeams.front().second;
                Obj<WeldingDetector>::GetInstance()->m_ImageTeams.pop();

                WeldingResult result;
                result.id = index;
                //SegandObjDetec(result);//生成目标检测图和分割图
                Process(index, src, result);
                m_Result.push(result);
            }
            printf("process count: %ld\n", count++);
            lock.unlock();
            Sleep(4);
        }
    }
}

void WeldingDetector::Process(int id, const cv::Mat& src, WeldingResult& result)
{
    clock_t start = clock();
    result.NO_HX_NGReults = OK;//判定初始化，每次图进来更新NG/OK默认状态
    std::vector<BBox>bboxs;
    cv::Mat image = src.clone();
    //1.面积计算及尺寸测量
    float area, hx_w, hx_h;
    HXResult hxResult{};
    TBResult YJResult{};
    float pix2mmScaleX, pix2mmScaleY;
    result.FusionMap = image;
    image = resize_with_padding(image, 640, 640, cv::Scalar(114, 114, 114));
    m_Detector[id].Infer(image, bboxs, conf_thresh, nms_thresh, 400);
    if (id == 0)
    {
        pix2mmScaleX = InParam.pix2mmScale_F_x;
        pix2mmScaleY = InParam.pix2mmScale_F_y;
    }
    else
    {
        pix2mmScaleX = InParam.pix2mmScale_Z_x;
        pix2mmScaleY = InParam.pix2mmScale_Z_y;
    }
    //添加处理 
    if (bboxs.size() == 0)
    {
        result.NG_OKflag = TRUE;
        result.NO_HX_NGReults = NG;
    }
    for (int i = 0; i < bboxs.size(); i++)
    {
        if (bboxs[i].label == 0)//焊锡处理
        {
            float bbox_x1 = bboxs[i].x1;
            float bbox_y1 = bboxs[i].y1;
            float bbox_x2 = bboxs[i].x2;
            float bbox_y2 = bboxs[i].y2;
            hx_w = bbox_x2 - bbox_x1;
            hx_h = bbox_y2 - bbox_y1;
            //输出结果
            hxResult.hxid = i;
            cv::Mat ROIsrc = image.clone();
            //取检测框ROI区域，适当扩大范围
            //范围约束
            int EXPAN = 80;
            int roi_x = int((((bboxs[i].x1 - EXPAN) < (0)) ? 0 : (bboxs[i].x1 - EXPAN)));
            int roi_y = int((((bboxs[i].y1 - EXPAN) < (0)) ? 0 : (bboxs[i].y1 - EXPAN)));
            int roi_w = int((roi_x + hx_w + 2 * EXPAN) > (image.cols) ? (image.cols - roi_x) : (hx_w + 2 * EXPAN));
            int roi_h = int((roi_y + hx_h + 2 * EXPAN) > (image.rows) ? (image.rows - roi_y) : (hx_h + 2 * EXPAN));
            //
            cv::Rect HXroi(roi_x, roi_y, roi_w, roi_h);
            cv::Mat HX_Crop = ROIsrc(HXroi);
            HX_Crop = resize_with_paddingPlus(HX_Crop, 640, 640, cv::Scalar(114, 114, 114));
            bool AreaFlag = getContourArea(id, HX_Crop, result);
            if (!AreaFlag)
            {
                std::cerr << "未检测到瑕疵面积! " << std::endl;
            }
            else
            {
                if (result.HX_Area != 0)
                {
                    //NG判定逻辑代码
                    if (result.HX_Area < InParam.min_area || result.HX_Area > InParam.max_area)
                    {
                        result.NG_OKflag = TRUE;
                        result.NO_HX_NGReults = HXAREA_Err;//尺寸NG
                    }
                }
            }
            if (InParam.AutoBDswitch)
            {
                float fs_hx_w = hx_w/scale_grobal;
                float fs_hx_h = hx_h/scale_grobal;
                std::ostringstream ss_w,ss_h;
                ss_w << std::fixed << std::setprecision(2) << fs_hx_w;
                ss_h << std::fixed << std::setprecision(2) << fs_hx_h;
                cv::putText(image, "BDPix: X:" + ss_w.str(), cv::Point(240, 80), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 0, 255), 2);
                cv::putText(image, "Y:" + ss_h.str(), cv::Point(360, 110), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 0, 255), 2);
            }
            //尺寸换算
            hx_w = (hx_w * pix2mmScaleX) / scale_grobal;
            hx_h = (hx_h * pix2mmScaleY) / scale_grobal;
            //NG判定逻辑代码
            if (hx_h < InParam.min_h || hx_h > InParam.max_h)
            {
                result.NG_OKflag = TRUE;
                if (result.NO_HX_NGReults == 0 || result.NO_HX_NGReults > 1) result.NO_HX_NGReults = HXSIZE_H_Err;
            }
            if (hx_w < InParam.min_w || hx_w > InParam.max_w)
            {
                result.NG_OKflag = TRUE;
                if (result.NO_HX_NGReults == 0 || result.NO_HX_NGReults > 2) result.NO_HX_NGReults = HXSIZE_W_Err;
            }
            hxResult.hx_weight = hx_w;
            hxResult.hx_height = hx_h;
            hxResult.x1 = bbox_x1;
            hxResult.y1 = bbox_y1;
            hxResult.x2 = bbox_x2;
            hxResult.y2 = bbox_y2;
            result.hxResult.push_back(hxResult);
            cv::rectangle(image, cv::Point(bbox_x1, bbox_y1), cv::Point(bbox_x2, bbox_y2),cv::Scalar(0,255,0),2);
        }
        else if (bboxs[i].label == 1)//引脚处理(后面添加引脚管理)
        {
            YJResult.x1 = bboxs[i].x1;
            YJResult.y1 = bboxs[i].y1;
            YJResult.x2 = bboxs[i].x2;
            YJResult.y2 = bboxs[i].y2;
            YJResult.YJ_H = bboxs[i].y2 - bboxs[i].y1;
            YJResult.YJ_W = bboxs[i].x2 - bboxs[i].x1;
            if (bboxs.size() == 1)
            {
                result.NG_OKflag = TRUE;//避免空白图像检测一个引脚导致OK判定
                result.NO_HX_NGReults = YJ_Err;//焊锡丢失问题，或者归纳为单个引脚问题
            }
            cv::rectangle(image, cv::Point(YJResult.x1, YJResult.y1), cv::Point(YJResult.x2, YJResult.y2), cv::Scalar(255, 0, 0), 2);
        }
        //else if (bboxs[i].label == 1)
        //{
        //    for (int i = 0; i < result; i++)
        //    {

        //    }
        //}
    }
    if (YJResult.x2 == 0)//只检测焊锡未检测引脚
    {
        result.NG_OKflag = TRUE;
        if (result.NO_HX_NGReults == 0 || result.NO_HX_NGReults > 3) result.NO_HX_NGReults = YJ_Err;
    }
    //二轮判定 焊锡中心偏移检测
    for (int i = 0; i < result.hxResult.size(); i++)
    {
        float center_PYRatio, hx_center, yj_center, center_PYpixel;
        hx_center = (result.hxResult[i].x1 + result.hxResult[i].x2) / 2;
        yj_center = (YJResult.x1 + YJResult.x2) / 2;
        center_PYpixel = yj_center - hx_center;//像素距离
        center_PYRatio = (yj_center - result.hxResult[i].x1) / (result.hxResult[i].x2 - yj_center + 1e-8);
        center_PYRatio = center_PYRatio / 2 + 1 / (2 * center_PYRatio);//对勾函数
        //center_PY = (std::abs(center_PYpixel) * pix2mmScaleX) / scale_grobal;//实际距离
        result.hxResult[i].center_pianyi = center_PYRatio;
        result.hxResult[i].PixelPY = center_PYpixel;
        if (center_PYRatio > InParam.max_PY)
        {
            result.NG_OKflag = TRUE;
            if (result.NO_HX_NGReults == 0 || result.NO_HX_NGReults > 4) result.NO_HX_NGReults = HXPY_Err;
        }
        else if (center_PYRatio < 0)
        {
            result.hxResult[i].center_pianyi = 0;
            result.hxResult[i].PixelPY = 0;
        }
    }
    //三轮判定 焊接位置不良
    for (int i = 0; i < result.hxResult.size(); i++)
    {
        float dis, tbtohx_dis, tbtohx_pixeldis;
        dis = YJResult.YJ_H;
        tbtohx_pixeldis = (((dis) > (0)) ? (dis) : (0)) - 1;
        tbtohx_dis = (tbtohx_pixeldis * pix2mmScaleY) / scale_grobal;//实际距离
        result.hxResult[i].TBtoHX_distance = tbtohx_dis;
        result.hxResult[i].Pixeldis = tbtohx_pixeldis;
        if (tbtohx_dis > InParam.max_TBDis)
        {
            result.NG_OKflag = TRUE;
            if (result.NO_HX_NGReults == 0 || result.NO_HX_NGReults > 5) result.NO_HX_NGReults = TBDIS_Err;
        }
    }
    //四轮判定，瑕疵检测
    //黑点及露铜检测
    for (int i = 0; i < bboxs.size(); i++)
    {
        //if (bboxs[i].label == 2 || bboxs[i].label == 3)
        //{
        //    if (bboxs[i].label == 3)
        //    {
        //        if (result.NO_HX_NGReults == 0 || result.NO_HX_NGReults > 5) result.NO_HX_NGReults = LT_Err;
        //    }
        //    else
        //    {
        //        if (NGclass == "NG")
        //        {
        //            if (result.NO_HX_NGReults == 0 || result.NO_HX_NGReults > 6) result.NO_HX_NGReults = HD_Err;
        //        }
        //    }
        //    result.NG_OKflag = TRUE;
        //    cv::rectangle(image, cv::Point(bboxs[i].x1, bboxs[i].y1), cv::Point(bboxs[i].x2, bboxs[i].y2), cv::Scalar(255, 0, 0), 2);
        //}
        if (bboxs[i].label == 3)
        {
            if (result.NO_HX_NGReults == 0 || result.NO_HX_NGReults > 6)
            {
                if (result.LT_MaxArea > InParam.LT_MAXArea_max || result.LT_SumArea > InParam.LT_ALLArea_max)
                {
                    result.NO_HX_NGReults = LT_Err;
                    result.NG_OKflag = TRUE;
                    cv::rectangle(image, cv::Point(bboxs[i].x1, bboxs[i].y1), cv::Point(bboxs[i].x2, bboxs[i].y2), cv::Scalar(0, 255, 255), 2);
                }
            }
        }
        if (bboxs[i].label == 2)
        {
            if (result.NO_HX_NGReults == 0 || result.NO_HX_NGReults > 7)
            {
                if (result.HD_MaxArea > InParam.HD_MAXArea_max || result.HD_SumArea > InParam.HD_ALLArea_max)
                {
                    result.NO_HX_NGReults = HD_Err;
                    result.NG_OKflag = TRUE;
                    cv::rectangle(image, cv::Point(bboxs[i].x1, bboxs[i].y1), cv::Point(bboxs[i].x2, bboxs[i].y2), cv::Scalar(0, 255, 255), 2);
                }
            }
        }
    }
    if (result.NG_OKflag)
    {
        if (bboxs.size() > 0)
        {
            for (int i = 0; i < result.hxResult.size(); i++)
            {
                int center_x = int((result.hxResult[i].x1 + result.hxResult[i].x2) / 2);
                int center_y = int((result.hxResult[i].y1 + result.hxResult[i].y2) / 2);
                int center_y_down = int(result.hxResult[i].y2 + 20);
                cv::line(image, cv::Point(center_x + result.hxResult[i].PixelPY, center_y_down), cv::Point(center_x + result.hxResult[i].PixelPY, YJResult.y1 - 20), cv::Scalar(221, 10, 221), 2);
                cv::line(image, cv::Point(result.hxResult[i].x1 - 20, YJResult.y1), cv::Point(result.hxResult[i].x2 + 20, YJResult.y1), cv::Scalar(255, 255, 0), 2);
            }
        }
    }
    else
    {
        result.NO_HX_NGReults = OK;
        for (int i = 0; i < result.hxResult.size(); i++)
        {
            int center_x = int((result.hxResult[i].x1 + result.hxResult[i].x2) / 2);
            int center_y = int((result.hxResult[i].y1 + result.hxResult[i].y2) / 2);
            int center_y_down = int(result.hxResult[i].y2 + 20);
            cv::line(image, cv::Point(center_x + result.hxResult[i].PixelPY, center_y_down), cv::Point(center_x + result.hxResult[i].PixelPY, YJResult.y1 - 20), cv::Scalar(221, 10, 221), 2);
            cv::line(image, cv::Point(result.hxResult[i].x1 - 20, YJResult.y1), cv::Point(result.hxResult[i].x2 + 20, YJResult.y1), cv::Scalar(255, 255, 0), 2);
        }
    }
    if (image.empty())
    {
        result.dst = src;
    }
    else
    {
        result.dst = image;
    }
    clock_t end = clock();

    std::cout << "consume : " << static_cast<double>(end - start) / CLOCKS_PER_SEC << " s\n";
}

/**
 * @brief 处理图像并返回分割轮廓的面积
 * @param id 处理ID，用于选择分割检测器
 * @param image 输入图像
 * @return 分割轮廓面积（像素单位），失败返回-1
 */
bool WeldingDetector::getContourArea(int id, cv::Mat& image, WeldingResult& result) {
    //面积转换系数
    double ratio = (InParam.pix2mmScale_F_x * InParam.pix2mmScale_F_y) / (scale_grobalPlus * scale_grobalPlus);
    try {
        // 检查输入图像有效性
        if (image.empty()) {
            throw std::runtime_error("输入图像为空");
        }

        // 检查ID有效性
        if (id < 0 || id >= static_cast<int>(m_SegDectector.size())) {
            throw std::runtime_error("无效的分割检测器ID");
        }

        // 定义分割网络输出和参数
        std::vector<Instance> Segbboxs; // 分割结果
        float conf_thresh = 0.5; // 置信度阈值，可根据需要调整
        float nms_thresh = 0.3;  // NMS阈值，可根据需要调整
        int time_out = 600;   // 超时控制
        //clock_t start = clock();
        // 调用分割网络
        m_SegDectector[id].Infer1(image, Segbboxs, conf_thresh, nms_thresh, time_out);//容易超时检测不到
        //clock_t end = clock();

        //std::cout << "consume : " << static_cast<double>(end - start) / CLOCKS_PER_SEC << " s\n";
        // 检查是否有分割结果
        if (Segbboxs.empty()) {
            return FALSE; // 未检测到任何分割区域
        }
        //检测输出id
        for (int i = 0; i < Segbboxs.size(); i++)
        {
            if (Segbboxs[i].label == 0)//以焊锡为主体进行检测
            {
                printf("焊锡检出\n");
                cv::Mat HX_mask = cv::Mat::zeros(image.size(), CV_8UC1);
                HX_mask = Segbboxs[i].mask;
                cv::Mat binary_mask;
                cv::threshold(HX_mask, binary_mask, 0, 255, cv::THRESH_BINARY);
                // 查找轮廓
                std::vector<std::vector<cv::Point>> contours;
                cv::findContours(binary_mask, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

                if (contours.empty()) {
                    return FALSE; // 未检测到轮廓
                }
                double maxArea = 0.0;
                //小焊锡球在这里做NG判断。
                for (const auto& contour : contours) {
                    double area = cv::contourArea(contour);
                    if (maxArea < area)
                    {
                        maxArea = area;
                    }
                }
                result.HX_Area = maxArea * ratio;
            }
            else if (Segbboxs[i].label == 1)//黑点检测
            {
                printf("黑点检出\n");
                int HDcounts = 0;
                cv::Mat HD_mask = cv::Mat::zeros(image.size(), CV_8UC1);
                HD_mask = Segbboxs[i].mask;
                cv::Mat binary_mask;
                cv::threshold(HD_mask, binary_mask, 0, 255, cv::THRESH_BINARY);
                // 查找轮廓
                std::vector<std::vector<cv::Point>> contours;
                cv::findContours(binary_mask, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

                if (contours.empty()) {
                    return FALSE; // 未检测到轮廓
                }
                double Maxarea = 0, SumArea = 0;
                for (const auto& contour : contours) {
                    double area = cv::contourArea(contour);
                    area = area * ratio;
                    if (area > InParam.HD_min)
                    {
                        if (Maxarea < area)
                        {
                            Maxarea = area;
                        }
                        HDcounts++;
                        SumArea += area;
                    }
                }
                result.HD_MaxArea = Maxarea;
                result.HD_SumArea = SumArea;
            }
            else if (Segbboxs[i].label == 2)
            {
                printf("漏铜检出\n");
                int LTcounts = 0;
                cv::Mat LT_mask = cv::Mat::zeros(image.size(), CV_8UC1);
                LT_mask = Segbboxs[i].mask;
                cv::Mat binary_mask;
                cv::threshold(LT_mask, binary_mask, 0, 255, cv::THRESH_BINARY);
                // 查找轮廓
                std::vector<std::vector<cv::Point>> contours;
                cv::findContours(binary_mask, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

                if (contours.empty()) {
                    return FALSE; // 未检测到轮廓
                }
                double Maxarea = 0, SumArea = 0;
                for (const auto& contour : contours) {
                    double area = cv::contourArea(contour);
                    area = area * ratio;
                    if (Maxarea < area)
                    {
                        Maxarea = area;
                    }
                    LTcounts++;
                    SumArea += area;
                }
                result.LT_MaxArea = Maxarea;
                result.LT_SumArea = SumArea;
            }

        }
        return TRUE;//分割检测完成
    }
    catch (const std::exception& e) {
        std::cerr << "处理异常 (ID: " << id << "): " << e.what() << std::endl;
        return FALSE;
    }
}

void WeldingDetector::SegandObjDetec(WeldingResult& result)
{
    //确定图像文件夹路径循环读取。4个一组
    std::string folderPath = "D:/HJC20250916/1T2/NJK_1T2/all_ZFALL";
    // 检查文件夹是否存在
    if (!fs::exists(folderPath)) {
        std::cerr << "错误: 文件夹不存在: " << folderPath << std::endl;
    }
    //std::vector<std::vector<cv::Mat>> imageGroups = loadImageGroups(folderPath);
        // 获取所有BMP文件
    std::vector<std::string> imageFiles;
    for (const auto& entry : fs::directory_iterator(folderPath)) {
        if (entry.path().extension() == ".JPG" || entry.path().extension() == ".jpg") {
            imageFiles.push_back(entry.path().filename().string());
        }
    }

    // 按文件名排序
    std::sort(imageFiles.begin(), imageFiles.end());
    cv::Mat ResImg;
    int count_id = 1;
    std::vector<BBox>bboxs;
    for (auto& filename : imageFiles) {
        std::string fullPath = folderPath + "/" + filename;
        ResImg = cv::imread(fullPath, cv::IMREAD_COLOR);
        //ResImg = MergeMultiLightImages(group);
        //cv::imwrite(folderPath + "/res_new/" + std::to_string(count_id) + ".jpg", ResImg);
        ResImg = resize_with_padding(ResImg, 640, 640, cv::Scalar(114, 114, 114));
        //图像校准
        int index = count_id % 2;
        m_Detector[index].Infer(ResImg, bboxs, conf_thresh, nms_thresh, 600);
        printf("目前检测第%d张图\n", count_id);
        clock_t start = clock();
        for (int i = 0; i < bboxs.size(); i++)
        {
            if (bboxs[i].label == 0)//焊锡处理
            {
                //cv::rectangle(ResImg, cv::Point(bboxs[i].x1, bboxs[i].y1), cv::Point(bboxs[i].x2, bboxs[i].y2), cv::Scalar(255, 0, 0), 2);
                float hx_w = bboxs[i].x2 - bboxs[i].x1;
                float hx_h = bboxs[i].y2 - bboxs[i].y1;
                cv::Mat ROIsrc = ResImg.clone();
                //取检测框ROI区域，适当扩大范围
                //范围约束
                int EXPAN = 80;
                int roi_x = int((((bboxs[i].x1 - EXPAN) < (0)) ? 0 : (bboxs[i].x1 - EXPAN)));
                int roi_y = int((((bboxs[i].y1 - EXPAN) < (0)) ? 0 : (bboxs[i].y1 - EXPAN)));
                int roi_w = int((roi_x + hx_w + 2 * EXPAN) > (ResImg.cols) ? (ResImg.cols - roi_x) : (hx_w + 2 * EXPAN));
                int roi_h = int((roi_y + hx_h + 2 * EXPAN) > (ResImg.rows) ? (ResImg.rows - roi_y) : (hx_h + 2 * EXPAN));
                //
                cv::Rect HXroi(roi_x, roi_y, roi_w, roi_h);
                //cv::rectangle(ROIsrc, cv::Point(bboxs[i].x1, bboxs[i].y1), cv::Point(bboxs[i].x2, bboxs[i].y2), cv::Scalar(0, 255, 0), 2);
                cv::Mat HX_Crop = ROIsrc(HXroi);
                HX_Crop = resize_with_paddingPlus(HX_Crop, 640, 640, cv::Scalar(114, 114, 114));
                //bool AreaFlag = getContourArea(index, HX_Crop, result);
                //if (!AreaFlag)
                //{
                //    std::cerr << "未检测到瑕疵面积! "<< std::endl;
                //}
                cv::imwrite(folderPath + "/res_HX/" + std::to_string(count_id) + "-" + std::to_string(i) + ".jpg", HX_Crop);
            }
            if (bboxs[i].label == 2)//黑点处理
            {
                //cv::rectangle(ResImg, cv::Point(bboxs[i].x1, bboxs[i].y1), cv::Point(bboxs[i].x2, bboxs[i].y2), cv::Scalar(255, 0, 0), 2);
                float hx_w = bboxs[i].x2 - bboxs[i].x1;
                float hx_h = bboxs[i].y2 - bboxs[i].y1;
                cv::Mat ROIsrc = ResImg.clone();
                //取检测框ROI区域，适当扩大范围
                //范围约束
                int EXPAN = 80;
                int roi_x = int((((bboxs[i].x1 - EXPAN) < (0)) ? 0 : (bboxs[i].x1 - EXPAN)));
                int roi_y = int((((bboxs[i].y1 - EXPAN) < (0)) ? 0 : (bboxs[i].y1 - EXPAN)));
                int roi_w = int((roi_x + hx_w + 2 * EXPAN) > (ResImg.cols) ? (ResImg.cols - roi_x) : (hx_w + 2 * EXPAN));
                int roi_h = int((roi_y + hx_h + 2 * EXPAN) > (ResImg.rows) ? (ResImg.rows - roi_y) : (hx_h + 2 * EXPAN));
                //
                cv::Rect HXroi(roi_x, roi_y, roi_w, roi_h);
                cv::Mat HX_Crop = ROIsrc(HXroi);
                HX_Crop = resize_with_paddingPlus(HX_Crop, 640, 640, cv::Scalar(114, 114, 114));
                //bool AreaFlag = getContourArea(index, HX_Crop, result);
                //if (!AreaFlag)
                //{
                //    std::cerr << "未检测到瑕疵面积! " << std::endl;
                //}
                cv::imwrite(folderPath + "/res_HD/" + std::to_string(count_id) + "-" + std::to_string(i) + ".jpg", HX_Crop);
            }
            if (bboxs[i].label == 3)//露铜处理
            {
                //cv::rectangle(ResImg, cv::Point(bboxs[i].x1, bboxs[i].y1), cv::Point(bboxs[i].x2, bboxs[i].y2), cv::Scalar(255, 0, 0), 2);
                float hx_w = bboxs[i].x2 - bboxs[i].x1;
                float hx_h = bboxs[i].y2 - bboxs[i].y1;
                cv::Mat ROIsrc = ResImg.clone();
                //取检测框ROI区域，适当扩大范围
                //范围约束
                int EXPAN = 80;
                int roi_x = int((((bboxs[i].x1 - EXPAN) < (0)) ? 0 : (bboxs[i].x1 - EXPAN)));
                int roi_y = int((((bboxs[i].y1 - EXPAN) < (0)) ? 0 : (bboxs[i].y1 - EXPAN)));
                int roi_w = int((roi_x + hx_w + 2 * EXPAN) > (ResImg.cols) ? (ResImg.cols - roi_x) : (hx_w + 2 * EXPAN));
                int roi_h = int((roi_y + hx_h + 2 * EXPAN) > (ResImg.rows) ? (ResImg.rows - roi_y) : (hx_h + 2 * EXPAN));
                //
                cv::Rect HXroi(roi_x, roi_y, roi_w, roi_h);
                cv::Mat HX_Crop = ROIsrc(HXroi);
                HX_Crop = resize_with_paddingPlus(HX_Crop, 640, 640, cv::Scalar(114, 114, 114));
                //bool AreaFlag = getContourArea(index, HX_Crop, result);
                //if (!AreaFlag)
                //{
                //    std::cerr << "未检测到瑕疵面积! " << std::endl;
                //}
                cv::imwrite(folderPath + "/res_LT/" + std::to_string(count_id) + "-" + std::to_string(i) + ".jpg", HX_Crop);
            }
        }
        count_id++;
        clock_t end = clock();
        std::cout << "Area_time : " << static_cast<double>(end - start) / CLOCKS_PER_SEC << " s\n";
    }
}

std::vector<std::vector<cv::Mat>> WeldingDetector::loadImageGroups(const std::string& folderPath) {
    std::vector<std::vector<cv::Mat>> groups;

    if (!fs::exists(folderPath)) {
        return groups;
    }

    // 获取所有BMP文件
    std::vector<std::string> imageFiles;
    for (const auto& entry : fs::directory_iterator(folderPath)) {
        if (entry.path().extension() == ".bmp" || entry.path().extension() == ".BMP") {
            imageFiles.push_back(entry.path().filename().string());
        }
    }

    // 按文件名排序
    std::sort(imageFiles.begin(), imageFiles.end());

    // 分组图像
    std::vector<cv::Mat> currentGroup;
    int currentGroupId = -1;

    for (const auto& filename : imageFiles) {
        // 查找最后两个下划线的位置
        size_t lastUnderscore = filename.rfind('_');
        if (lastUnderscore == std::string::npos) continue;

        size_t secondLastUnderscore = filename.rfind('_', lastUnderscore - 1);
        if (secondLastUnderscore == std::string::npos) continue;

        //size_t dotPos = filename.rfind('.');
        //if (dotPos == std::string::npos || dotPos <= lastUnderscore) continue;

        try {
            // 提取主序号和子序号
            int mainId = std::stoi(filename.substr(secondLastUnderscore + 1, lastUnderscore - secondLastUnderscore - 1));
            //int subId = std::stoi(filename.substr(lastUnderscore + 1, dotPos - lastUnderscore - 1));

            if (mainId != currentGroupId) {
                if (!currentGroup.empty() && currentGroup.size() == 4) {
                    groups.push_back(currentGroup);
                }
                currentGroupId = mainId;
                currentGroup.clear();
            }

            std::string fullPath = folderPath + "/" + filename;
            cv::Mat image = cv::imread(fullPath, cv::IMREAD_COLOR);

            if (!image.empty()) {
                currentGroup.push_back(image);
            }
        }
        catch (...) {
            continue;
        }
    }

    // 添加最后一组
    if (!currentGroup.empty() && currentGroup.size() == 4) {
        groups.push_back(currentGroup);
    }

    return groups;
}

void WeldingDetector::Report(std::function<void(WeldingResult)> callback)
{
    while (true) 
    {
        if (m_Result.size() > 0)
        {
            callback(m_Result.front());
            m_Result.pop();
        }
        Sleep(4);
    }
}

